﻿using Avalonia.Controls;
using Avalonia.Controls.Shapes;
using LightCAD.Core.Elements;
using netDxf.Entities;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata;
using System.Runtime.Intrinsics.X86;
using System.Text;
using System.Threading.Tasks;
using static LightCAD.Core.Elements.LcPolyLine;

namespace LightCAD.Drawing.Actions.Action
{
    public class PolygonAction : ElementAction
    {
        public static string CommandName;
        public static LcCreateMethod[] CreateMethods;



        internal static void Initilize()
        {
            ElementActions.Polygon = new PolygonAction();
            LcDocument.ElementActions.Add(BuiltinElementType.Polygon, ElementActions.Polygon);

        }
        private InElementsInputer InElementsInputer { get; set; }
        private ElementSetInputer ElementInputers { get; set; }
        private ElementInputer ElementInputer { get; set; }
        private CmdTextInputer CmdTextInputer { get; set; }
        private PointInputer PointInputer { get; set; }
        private PolygonAction() { }



        public PolygonAction(IDocumentEditor docEditor) : base(docEditor)
        {
            this.commandCtrl.WriteInfo("命令：POLYGON");
        }

        private LcCreateMethod GetMethod(string method)
        {
            if (method == null)
                return SetCurMethod(CreateMethods, 0);

            int getted = CreateMethods.ToList().FindIndex(m => m.Name == method);
            if (getted == -1)
                return SetCurMethod(CreateMethods, 0);
            else
                return SetCurMethod(CreateMethods, getted);
        }


        static PolygonAction()
        {
            CommandName = "POLYGON";
            CreateMethods = new LcCreateMethod[3];
            CreateMethods[0] = new LcCreateMethod()
            {
                Name = "CreatePolygon",
                Description = "创建多边形",
                Steps = new LcCreateStep[]
               {
                    new LcCreateStep { Name=  "Step0", Options= "POLYGON _polygon 输入侧面数:" },
                    new LcCreateStep { Name=  "Step1", Options= "POLYGON 指定多边形的中心点或[边(E)]:" },


               }
            };

            CreateMethods[1] = new LcCreateMethod()
            {
                Name = "CreatePolygonE",
                Description = "边边创建多边形",
                Steps = new LcCreateStep[]
               {

                    new LcCreateStep { Name=  "E_Step0", Options= "POLYGON 指定边的第一个端点:" },
                    new LcCreateStep { Name=  "E_Step1", Options= "POLYGON 指定边的第二个端点:" },


               }
            };

            CreateMethods[2] = new LcCreateMethod()
            {
                Name = "CreatePolygonC",
                Description = "中心点圆创建多边形",
                Steps = new LcCreateStep[]
              {

                    new LcCreateStep { Name=  "C_Step0", Options= "POLYGON 输入选项[内接于圆(I) 外切于圆(C)]:" },
                    new LcCreateStep { Name=  "C_Step1", Options= "REXTANG 指定半径:" },


              }
            };



        }



        private Vector2? Center { get; set; }     //圆心点
        private Vector2? BasePoint { get; set; }   //边的基准点   

        private Vector2? SecondPoint { get; set; }   //边的另一端点

        private Vector2? SecPoint { get; set; }   //圆上一点

        private int Sides { get; set; }           //边数

        private bool InCircle { get; set; }        //判断是否内接

        private string a { get; set; }                //辅助字符串，辅助实时渲染的判定

        private List<Curve2d> Segments { get; set; }       //边的集合

        private double Radius { get; set; }           //半径

        private PointInputer Inputer { get; set; }

        private string _methodName;
        private string _methodArg;


        public async void ExecCreate(string[] args = null)
        {
            var method = "CreatePolygon";
            if (args != null && args.Length > 0)
            {
                method = args[0];
            }
            var curMethod = this.GetMethod(method);
            _methodName = curMethod.Name;
            this.Inputer = new PointInputer(this.docEditor);
            this.StartCreating();

            curMethod = this.SetCurMethod(CreateMethods, 0);
            var step0 = SetCurStep(curMethod, 0);
            _methodName = curMethod.Name;
            var result0 = await Inputer.Execute(step0.Options);


            if (Inputer.isCancelled) { this.Cancel(); return; }
            if (result0.ValueX == null)
            {
                if (result0.Option != null && int.TryParse(result0.Option, out int optionValue))
                {
                    Sides = optionValue;
                    var step1 = SetCurStep(curMethod, 1);
                    var result1 = await Inputer.Execute(step1.Options);
                    if (Inputer.isCancelled) { this.Cancel(); return; }
                    if (result1.ValueX == null)
                    {
                        
                        if (result1.Option.ToUpper() == "E")
                        {

                            goto Method_CreatePolygonE_Step0;

                        }
                        
                       
                            if (result1.Option.ToUpper() != "E")
                        {

                            return;
                        }
                    }

                    if (result1.ValueX != null)

                    {

                        Center = (Vector2)result1.ValueX;
                        goto Method_CreatePolygonC_Step0;

                    }
                    
                    
                }
                else { return; }
            }
            else
            {
                return;
            }



        #region Method_CreatePolygonE_Step0
        Method_CreatePolygonE_Step0:

            curMethod = this.SetCurMethod(CreateMethods, 1);
            _methodName = curMethod.Name;
            var E_step0 = SetCurStep(curMethod, 0);
            var E_result0 = await Inputer.Execute(E_step0.Options);

            if (Inputer.isCancelled) { this.Cancel(); return; }
            if (E_result0.ValueX == null)
            {
                return;
            }
            if (E_result0.ValueX != null)
            {
                BasePoint = (Vector2)E_result0.ValueX;

                var E_step1 = SetCurStep(curMethod, 1);
                var E_result1 = await Inputer.Execute(E_step1.Options);
                if (Inputer.isCancelled) { this.Cancel(); return; }
                if (E_result1.ValueX == null) { return; }
                if (E_result1.ValueX != null)
                {
                    SecondPoint = (Vector2)E_result1.ValueX;
                    Segments = CreateSide(Sides, BasePoint, SecondPoint);
                    goto End;
                }

            }
        #endregion

        #region Method_CreatePolygonC_Step0
        Method_CreatePolygonC_Step0:

            curMethod = this.SetCurMethod(CreateMethods, 2);
            _methodName = curMethod.Name;
            var C_step0 = SetCurStep(curMethod, 0);
            var C_result0 = await Inputer.Execute(C_step0.Options);
            if (Inputer.isCancelled) { this.Cancel(); return; }
            if (C_result0.ValueX == null)

            {
                if (C_result0.Option.ToUpper() == "C")
                {
                    a = "C";
                    InCircle = false;
                    var C_step1 = SetCurStep(curMethod, 1);
                    var C_result1 = await Inputer.Execute(C_step1.Options);
                    if (Inputer.isCancelled) { this.Cancel(); return; }

                    if (C_result1.ValueX == null && double.TryParse(C_result1.Option, out double radius))
                    {
                        Radius = radius;
                    }

                    if (C_result1.ValueX != null)

                    {


                        SecPoint = (Vector2)C_result1.ValueX;
                        Radius = Vector2.Distance(Center, SecPoint);


                    }

                    else { return; }


                    Segments = CCreateCenter(Sides, Center, Radius, SecPoint);
                    goto End;
                }


                if (C_result0.Option.ToUpper() == "I")
                {
                    a = "I";
                    InCircle = true;
                    var C_step1 = SetCurStep(curMethod, 1);
                    var C_result1 = await Inputer.Execute(C_step1.Options);
                    if (Inputer.isCancelled) { this.Cancel(); return; }

                    if (C_result1.ValueX == null && double.TryParse(C_result1.Option, out double radius))
                    {

                        Radius = radius;
                    }


                    if (C_result1.ValueX != null)

                    {
                        SecPoint = (Vector2)C_result1.ValueX;
                        Radius = Vector2.Distance(Center, SecPoint);
                    }

                    else { return; }


                    Segments = ICreateCenter(Sides, Center, Radius, SecPoint);
                    goto End;
                }

            }
               

            if (C_result0.ValueX != null)
            {
                return;
            }
           





        #endregion

        End:
            CreatePolygon(Segments);
            this.Inputer = null;
            this.EndCreating();
        }

        private void CreatePolygon(List<Curve2d> Seg)  //最终渲染
        {
            if (Seg == null || Seg.Count <= 2)
            {
                // 如果线段列表为空或线段数量小于2，则无法创建多边形
                return;
            }
            var doc = this.docRt.Document;
            DocumentManager.CurrentRecorder.BeginAction("PolyLine");
            var PolyLine = doc.CreateObject<LcPolyLine>();
            PolyLine.IsClosed = true;

            PolyLine.Curve2ds = Seg;

            doc.ModelSpace.InsertElement(PolyLine);
            this.docRt.Action.ClearSelects();
            DocumentManager.CurrentRecorder.EndAction();



        }
        public double GetDegreesByTwoLine(Vector2 line1start, Vector2 line1End, Vector2 line2start, Vector2 line2End)
        {
            double x1 = line1start.X;
            double y1 = line1start.Y;
            double x2 = line1End.X;
            double y2 = line1End.Y;
            double x3 = line2start.X;
            double y3 = line2start.Y;
            double x4 = line2End.X;
            double y4 = line2End.Y;

            // 计算线段的向量表示
            double v1x = x2 - x1;
            double v1y = y2 - y1;
            double v2x = x4 - x3;
            double v2y = y4 - y3;

            // 计算向量的内积
            double dotProduct = v1x * v2x + v1y * v2y;

            // 计算向量的长度
            double magnitudeV1 = Math.Sqrt(v1x * v1x + v1y * v1y);
            double magnitudeV2 = Math.Sqrt(v2x * v2x + v2y * v2y);

            // 计算夹角余弦值
            double cosine = dotProduct / (magnitudeV1 * magnitudeV2);

            // 将夹角余弦值转换为角度
            double angleRadians = Math.Acos(cosine);
            double angleDegrees = angleRadians * 180 / Math.PI;
            return angleDegrees;
        }
        public int IsTopInLine(Vector2 line1start, Vector2 line1End, Vector2 point)
        {
            Vector2 S;
            Vector2 E;

            S = line1End;
            E = line1start;

            // }
            double Tmp = (S.Y - E.Y) * point.X + (E.X - S.X) * point.Y + S.X * E.Y - E.X * S.Y;
            if (Tmp == 0)
            {
                return 0;
            }
            if (Tmp > 0)
            {
                return 1;
            }
            else
            { return -1; }
            //                Tmp > 0 在左侧

            //Tmp = 0 在线上

            //Tmp < 0 在右侧
        }
        public override void DrawAuxLines(SKCanvas canvas)    //实时渲染
        {
            if (Center != null && a != null)
            {
                var mp = this.vportRt.PointerMovedPosition.ToVector2d();
                var wcs_mp = this.vportRt.ConvertScrToWcs(mp);         //鼠标移动点

                if (InCircle == true)
                {
                    Segments = ICreateCenter(Sides, Center, Vector2.Distance(wcs_mp, Center), wcs_mp);//内接圆
                }
                if (InCircle == false)
                {
                    Segments = CCreateCenter(Sides, Center, Vector2.Distance(wcs_mp, Center), wcs_mp);//外切圆
                }

                #region 废代码，学习用，不要删
                //  var line = new  Line2d() ;
                //  foreach (var item in Segments)
                //  {
                //      if (Line2d.PointInLine(new Line2d(item.Start, item.End), wcs_mp))
                //      {
                //          line = new Line2d(item.Start, item.End);
                //      }
                //  }

                //  Vector2 vector2 = new Vector2((line.Start.X+line.End.X)/2, (line.Start.Y + line.End.Y) / 2);
                ////  var rotateAngle = Vector2.GetAngle(vector2, wcs_mp);
                //  var rotateAngle = GetDegreesByTwoLine(Center, vector2, Center, wcs_mp);
                //  if (IsTopInLine(Center, vector2, wcs_mp) < 0)
                //  {
                //      rotateAngle = 360 - rotateAngle;
                //  }
                //  Matrix3 matrix3 = Matrix3.RotateInRadian(rotateAngle, Center);

                #endregion

                if (Segments != null)
                {
                    foreach (var item in Segments)
                    {
                        var sk_pre = this.vportRt.ConvertWcsToScr((item as Line2d).Start).ToSKPoint();
                        var sk_p = this.vportRt.ConvertWcsToScr((item as Line2d).End).ToSKPoint();
                        //var sk_pre = this.vportRt.ConvertWcsToScr(matrix3.MultiplyPoint(item.Start)).ToSKPoint();
                        //var sk_p = this.vportRt.ConvertWcsToScr(matrix3.MultiplyPoint(item.End)).ToSKPoint();
                        //辅助元素的颜色 
                        canvas.DrawLine(sk_pre, sk_p, new SKPaint { Color = this.vportRt.GetAuxColorValue(), IsStroke = true });
                        //   item.Start
                    }
                }
                // DrawAuxLine(canvas, firstPoint, wcs_mp, Constants.auxElementPen);
            }
            else
            {
                var mp = this.vportRt.PointerMovedPosition.ToVector2d();
                var wcs_mp = this.vportRt.ConvertScrToWcs(mp);         //鼠标移动点


                if (BasePoint != null)
                {

                    Segments = CreateSide(Sides, BasePoint, wcs_mp);

                    if (Segments != null)
                    {
                        foreach (var item in Segments)
                        {
                            var sk_pre = this.vportRt.ConvertWcsToScr((item as Line2d).Start).ToSKPoint();
                            var sk_p = this.vportRt.ConvertWcsToScr((item as Line2d).End).ToSKPoint();
                            //var sk_pre = this.vportRt.ConvertWcsToScr(matrix3.MultiplyPoint(item.Start)).ToSKPoint();
                            //var sk_p = this.vportRt.ConvertWcsToScr(matrix3.MultiplyPoint(item.End)).ToSKPoint();
                            //辅助元素的颜色 
                            canvas.DrawLine(sk_pre, sk_p, new SKPaint { Color = this.vportRt.GetAuxColorValue(), IsStroke = true });
                            //   item.Start
                        }
                    }
                }
                //}

            }




            //辅助元素的颜色 
            //   canvas.DrawLine(sk_pre, sk_p, sKPaint);
            //辅助曲线的颜色，包括辅助长度，辅助角度等

        }






        //根据确定的边画多边形
        public static List<Curve2d> CreateSide(int sides, Vector2 a, Vector2 b)
        {
            if (sides < 3)
            {
                return null;
                throw new ArgumentException("无效的边数");
            }

            // 计算边的长度和角度增量
            double sideLength = Vector2.Distance(a, b);
            double angleIncrement = 2 * Math.PI / sides;

            // 创建多边形的边
            List<Curve2d> segments = new List<Curve2d>();
            Vector2 currentPoint = a;

            for (int i = 0; i < sides; i++)
            {
                double angle = i * angleIncrement;
                double x = currentPoint.X + sideLength * Math.Cos(angle);
                double y = currentPoint.Y + sideLength * Math.Sin(angle);

                Line2d segi = new Line2d();
                segi.Start = currentPoint;
                segi.End = new Vector2(x, y);
                

                segments.Add(segi);

                currentPoint = segi.End;
            }

            var rotateAngle = Vector2.GetAngle(a, b);
            List<Curve2d> newSegments = new List<Curve2d>();
            if (segments != null)
            {

                foreach (var item in segments)
                {


                    Matrix3 matrix3 = Matrix3.RotateInRadian(rotateAngle, a);
                    Vector2 transformedStart = matrix3.MultiplyPoint((item as Line2d).Start);
                    Vector2 transformedEnd = matrix3.MultiplyPoint((item as Line2d).End);

                    // 创建新的边
                    Line2d newSegment = new Line2d();
                    newSegment.Start = transformedStart;
                    newSegment.End = transformedEnd;
                    

                    // 将新的边添加到集合
                    newSegments.Add(newSegment);

                }
            }

            segments = newSegments;
            return segments;
        }



        //根据边数，中心点和内接圆或外切圆半径画多边形
        public static List<Curve2d> ICreateCenter(int sides, Vector2 CenterPoint, double RadiusLength, Vector2 secc)        //内接于圆半径
        {

            if (sides < 3 || RadiusLength <= 0)
            {
                return null;
                throw new ArgumentException("无效的边数或半径长度");
            }
            //计算多边形的顶点
            List<Vector2> vertices = new List<Vector2>();
            double angleIncrement = 2 * Math.PI / sides;

            for (int i = 0; i < sides; i++)
            {
                double angle = i * angleIncrement;
                double x = CenterPoint.X + RadiusLength * Math.Cos(angle);
                double y = CenterPoint.Y + RadiusLength * Math.Sin(angle);
                vertices.Add(new Vector2(x, y));
            }

            //创建多边形的边
            List<Curve2d> Segments = new List<Curve2d>();
            for (int i = 0; i < sides - 1; i++)
            {
                Line2d segi = new Line2d();
                segi.Start = vertices[i];
                segi.End = vertices[i + 1];
                Segments.Add(segi);

                if (i + 2 == sides)
                {
                    Line2d segi2 = new Line2d();
                    segi2.Start = vertices[i + 1];
                    segi2.End = vertices[0];
                    Segments.Add(segi2);
                }


            }
            var rotateAngle = Vector2.GetAngle(CenterPoint, secc);
            List<Curve2d> newSegments = new List<Curve2d>();
            if (Segments != null)
            {

                foreach (var item in Segments)
                {


                    Matrix3 matrix3 = Matrix3.RotateInRadian(rotateAngle, CenterPoint);
                    Vector2 transformedStart = matrix3.MultiplyPoint((item as Line2d).Start);
                    Vector2 transformedEnd = matrix3.MultiplyPoint((item as Line2d).End);

                    // 创建新的边
                    Line2d newSegment = new Line2d();
                    newSegment.Start = transformedStart;
                    newSegment.End = transformedEnd;

                    // 将新的边添加到集合
                    newSegments.Add(newSegment);



                }
            }
            Segments = newSegments;
            return Segments;
        }



        public static List<Curve2d> CCreateCenter(int sides, Vector2 CenterPoint, double RadiusLength, Vector2 secc)        //外切于圆半径
        {



            if (sides < 3 || RadiusLength <= 0)
            {
                return null;
                throw new ArgumentException("无效的边数或半径长度");
            }
            //计算多边形的顶点

            List<Vector2> vertices = new List<Vector2>();
            double angleIncrement = 2 * Math.PI / sides;
            double angleIncrementHalf = angleIncrement / 2;
            double radiusLength = RadiusLength / Math.Cos(angleIncrementHalf);


            for (int i = 0; i < sides; i++)
            {
                double angle = i * angleIncrement + Math.PI / sides; // 调整角度
                double x = CenterPoint.X + radiusLength * Math.Cos(angle);
                double y = CenterPoint.Y + radiusLength * Math.Sin(angle);
                vertices.Add(new Vector2(x, y));
            }

            //创建多边形的边
            List<Curve2d> Segments = new List<Curve2d>();
            for (int i = 0; i < sides - 1; i++)
            {
                Line2d segi = new Line2d();
                segi.Start = vertices[i];
                segi.End = vertices[i + 1];
                Segments.Add(segi);

                if (i + 2 == sides)
                {
                    Line2d segi2 = new Line2d();
                    segi2.Start = vertices[i + 1];
                    segi2.End = vertices[0];
                    Segments.Add(segi2);
                }


            }
            var rotateAngle = Vector2.GetAngle(CenterPoint, secc);
            List<Curve2d> newSegments = new List<Curve2d>();
            if (Segments != null)
            {

                foreach (var item in Segments)
                {


                    Matrix3 matrix3 = Matrix3.RotateInRadian(rotateAngle, CenterPoint);
                    Vector2 transformedStart = matrix3.MultiplyPoint((item as Line2d).Start);
                    Vector2 transformedEnd = matrix3.MultiplyPoint((item as Line2d).End);

                    // 创建新的边
                    Line2d newSegment = new Line2d();
                    newSegment.Start = transformedStart;
                    newSegment.End = transformedEnd;

                    // 将新的边添加到集合
                    newSegments.Add(newSegment);
                }
            }
            Segments = newSegments;
            return Segments;
        }









    }

}

